package com.lanhai.longheng.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.lanhai.longheng.MsgCore; 
import com.lanhai.longheng.beans.AgvBean;
import com.lanhai.longheng.beans.ControlAreaBean;
import com.lanhai.longheng.dao.ControlAreaDao;
import com.lanhai.longheng.interfaces.IAgv;
import com.lanhai.longheng.interfaces.IAgvEvent;
import com.lanhai.longheng.interfaces.IControlArea;
import com.lanhai.longheng.mapper.ControlAreaMapper;
import com.lanhai.longheng.utils.Tools; 
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; 

@Service 
public class ControlAreaImpl implements IControlArea{
	 
	@Autowired
	ControlAreaMapper caMapper;
	
	@Autowired
	JedisPool jedisPool;
	
	@Autowired
	IAgvEvent iAgvEvent;
	
	@Autowired
	IAgv iAgv;
	
	//所有的缓存区域
	static  List<ControlAreaDao> list=Collections.synchronizedList( new ArrayList<ControlAreaDao>());
	
	//锁定的区域
	static Map<Long, ControlAreaBean> lockMap=Collections.synchronizedMap( new HashMap<Long,ControlAreaBean>());
	static Object locker =new Object();
	/**
	 * 是否到达某区域 
	 */
	@Override
	public   long getAreaId(int x, int y) { 
		if(list==null||list.size()==0 ) {  
			getAllList();
		} 
	    if(list.size()>0) {
		    for(ControlAreaDao dao:list) {
		    	if(dao.getMinX()<=x&&x<=dao.getMaxX() && dao.getMinY()<=y && y<=dao.getMaxY()) {
		    		return dao.getAreaId();
		    	}
		    }
	    }
		return 0;
	}
	
	
	

	/**
	 *锁定区域
	 */
	@Override
	public synchronized boolean lockArea(long areaId, int agvId) {  
		ControlAreaBean bean=getBean(areaId);
		if(bean.isLocking()&&bean.getAgvid()==agvId) {
			return true;
		}
		if(bean.isLocking()==false) {
			bean.setLocking(true); 
			bean.setAgvid(agvId);
			saveCache(bean);
			return true;
		} 
		return false;
	}

 

	/**
	 *区域解锁。如果这个区域还有其它小车
	 */
	@Override
	public synchronized void unlockArea(long areaId) {   
		ControlAreaBean bean=getBean(areaId); 
		if(bean.getStopAgv()==null||bean.getStopAgv().size()==0) {
			bean.setLocking(false);
			bean.setAgvid(0);
			saveCache(bean); 
			return;
		}
		//找到队列中第一辆车，并移除掉
		 int agvid=Tools.strToInt( bean.getStopAgv().get(0));
		 bean.getStopAgv().remove(0); 
		 bean.setAgvid(agvid); 
		 saveCache(bean); 
		  
		 //启动小车
		 AgvBean agv=iAgv.getBean(agvid);
		 if(agv!=null) {
			 if(agv.getAreaId()==bean.getAreaId()) {
				 //在同一个区域内 
				 MsgCore.sendMsg(agv.getAgvId(), "交管允许前进");
				 iAgvEvent.stopOrstart(agv, false);
			 }else {
				 //目标小车已经离开，继续解锁
				 unlockArea(areaId);
			 } 
		 } else {
			 //小车不存在,继续下一辆车
			 unlockArea(areaId);
		 }
	}

	/**
	 *移除小车
	 */
	@Override
	public  synchronized void removeStopAgv(  int agvId) {
		//先拿所有的区域
		List<Long> ids=caMapper.getAreaIdList();
		if(ids!=null&&ids.size()>0) {
			for(long areaId:ids) {
				ControlAreaBean bean=getBean(areaId); 
				if(bean.getStopAgv()!=null&&bean.getStopAgv().size()>0) {
					if(bean.getStopAgv().contains(""+agvId)) {
						bean.getStopAgv().remove(""+agvId);
						saveCache(bean);  
					} 
				}
			}
		}
		
		
	}

	/**
	 *判断小车是否是某路段的上锁者
	 */
	@Override
	public boolean isLocker(long areaId, int agvId) {
		ControlAreaBean bean=getBean(areaId); 
		if(bean.isLocking()==false) return false;
		 return  bean.getAgvid()==agvId;
	 
	}

 

	/**
	 *添加交管的小车
	 */
	@Override
	public synchronized boolean addStopAgv(long areaId, int agvId) {
		ControlAreaBean bean=getBean(areaId); 
		String ak=""+agvId;  
		//交管被锁+锁的车不是当前小车+列表中没有当前小车
		if(bean.isLocking()&&bean.getAgvid()!=agvId&& bean.getStopAgv().contains(ak)==false  ) {
			bean.getStopAgv().add(ak);
			saveCache(bean);
			return true;
		}else {
			return false;
		}
		
		
	}

	/**
	 *是否服务区
	 */
	@Override
	public boolean isService(long areaId) {
		if(list==null||list.size()==0 ) {  
			getAllList();
		} 
	    if(list.size()>0) {
		    for(ControlAreaDao dao:list) {
		    	if(dao.getAreaId()==areaId) {
		    		return  dao.getAreaType()>0;
		    	}
		    }
	    }
	     return false;
	}

	/**
	 * 从redis中拿数据
	 */
	@Override
	public synchronized ControlAreaBean getBean(long areaId) {
		ControlAreaBean bean=lockMap.get(areaId);
		if (bean == null) {
			String mainkey = "controlarea";
			String key = String.format("%d", areaId);
			Gson gson = new Gson();
			Jedis jd = jedisPool.getResource();
			String json = jd.hget(mainkey, key);
			if (json != null && json.isEmpty() == false) {
				try {
					bean = gson.fromJson(json, ControlAreaBean.class);
				} catch (Exception e) {

				}
			}
			if (bean == null) {
				if (list == null) {
					getAllList();
				}
				for (ControlAreaDao dao : list) {
					if (dao.getAreaId() == areaId) {
						bean = new ControlAreaBean();
						bean.setAreaId(dao.getAreaId());
						bean.setAgvid(0);
						bean.setLocking(false);
						json = gson.toJson(bean);
						jd.hset(mainkey, key, json);

						lockMap.put(areaId, bean);
						break;
					}
				}
			}
			jd.close();
		}
		return bean;
	}

	 

	//内部保存，不需要同步锁
	@Override
	public void saveCache(ControlAreaBean bean) {
		synchronized (locker) { 
			lockMap.put(bean.getAreaId(), bean);
			
			String mainkey = "controlarea";
			String key = String.format("%d", bean.getAreaId()); 
			Gson gson=new Gson();
			String json=gson.toJson(bean);
			Jedis jd=jedisPool.getResource(); 
			jd.hset(mainkey, key,json);
			jd.close();
		}
	}

	@Override
	public   void getAllList() {
		synchronized (locker) { 
			List<ControlAreaDao> tmp = caMapper.getAreaAll();
			if (tmp != null && tmp.size() > 0) {
				list.addAll(tmp);
			}
		}
	}




	@Override
	public ControlAreaDao getArea(long areaId) {
		if(list==null||list.size()==0 ) {  
			getAllList();
		} 
	    if(list.size()>0) {
		    for(ControlAreaDao dao:list) {
		    	if(dao.getAreaId()==areaId) {
		    		ControlAreaDao re=new ControlAreaDao();
		    		re.setAreaId(areaId);
		    		re.setMaxX((dao.getMaxX()+dao.getMinX())/2 );
		    		re.setMaxY((dao.getMaxY()+dao.getMinY())/2 );
		    		return re;
		    	}
		    }
	    } 
		return null;
	}




	@Override
	public void clearArea() {
		synchronized (locker) { 
			list.clear();
		}
	}




	
	/**
	 *移除指定区域内的小车
	 */
	@Override
	public void removeStopAgv(long areaId, int agvId) {

		ControlAreaBean bean = getBean(areaId);
		if (bean == null) return;
		synchronized (locker) {
			if (bean.getAgvid() != agvId) {
				// 不是当前小车锁定的
				if (bean.getStopAgv() != null && bean.getStopAgv().contains("" + agvId)) {
					bean.getStopAgv().remove("" + agvId);
					saveCache(bean);
					return;
				}
			} else {
				// 是当前小车锁定的
				if (bean.getStopAgv() == null || bean.getStopAgv().size() == 0) {
					// 没有其它车
					bean.setAgvid(0);
					bean.setLocking(false);
					saveCache(bean);
				} else {
					// 拿出第一辆车
					int agvid = Tools.strToInt(bean.getStopAgv().get(0));
					bean.getStopAgv().remove(0);
					bean.setAgvid(agvid);
					bean.setLocking(true);
					saveCache(bean);

					// 启动小车
					AgvBean agv = iAgv.getBean(agvid);

					if (agv != null) {
						if (agv.getAreaId() == bean.getAreaId()) {
							// 在同一个区域内
							MsgCore.sendMsg(agv.getAgvId(), "交管允许前进");
							iAgvEvent.stopOrstart(agv, false);
						}
					}
				}
			}

		}
	}

 
}
 
